<template>
  <div class="performance-monitor">
    <!-- 顶部状态区域 -->
    <div class="monitor-header">
      <div class="header-info">
        <h2>性能实时监控</h2>
        <div class="connection-status">
          <el-tag :type="connectionStatus === 'connected' ? 'success' : 'danger'" effect="dark">
            <el-icon><Connection /></el-icon>
            {{ connectionStatus === 'connected' ? '已连接' : '未连接' }}
          </el-tag>
        </div>
      </div>
      <div class="monitor-controls">
        <el-button-group>
          <el-button 
            :type="isMonitoring ? 'danger' : 'primary'" 
            @click="toggleMonitoring"
            :loading="loading">
            <el-icon><VideoPlay v-if="!isMonitoring" /><VideoPause v-else /></el-icon>
            {{ isMonitoring ? '停止监控' : '开始监控' }}
          </el-button>
          <el-button @click="refreshData">
            <el-icon><Refresh /></el-icon>
            刷新
          </el-button>
        </el-button-group>
      </div>
    </div>

    <!-- 监控面板 -->
    <div class="monitor-panels">
      <!-- 性能指标面板 -->
      <el-row :gutter="20">
        <el-col :span="12">
          <el-card class="monitor-card">
            <template #header>
              <div class="card-header">
                <span>TPS 趋势</span>
                <el-tag size="small">{{ currentData.avgTps || 0 }}</el-tag>
              </div>
            </template>
            <div ref="tpsChart" class="chart-container"></div>
          </el-card>
        </el-col>
        
        <el-col :span="12">
          <el-card class="monitor-card">
            <template #header>
              <div class="card-header">
                <span>响应时间</span>
                <el-tag size="small">{{ currentData.avgResponseTime || 0 }}ms</el-tag>
              </div>
            </template>
            <div ref="responseChart" class="chart-container"></div>
          </el-card>
        </el-col>
      </el-row>

      <!-- 系统资源面板 -->
      <el-row :gutter="20" style="margin-top: 20px;">
        <el-col :span="8">
          <el-card class="monitor-card">
            <template #header>
              <div class="card-header">
                <span>CPU 使用率</span>
                <el-tag size="small">{{ currentSystem.cpu?.percent?.toFixed(1) || 0 }}%</el-tag>
              </div>
            </template>
            <div ref="cpuChart" class="chart-container"></div>
          </el-card>
        </el-col>
        
        <el-col :span="8">
          <el-card class="monitor-card">
            <template #header>
              <div class="card-header">
                <span>内存使用率</span>
                <el-tag size="small">{{ currentSystem.memory?.percent?.toFixed(1) || 0 }}%</el-tag>
              </div>
            </template>
            <div ref="memoryChart" class="chart-container"></div>
          </el-card>
        </el-col>
        
        <el-col :span="8">
          <el-card class="monitor-card">
            <template #header>
              <div class="card-header">
                <span>网络流量</span>
                <el-tag size="small">{{ formatBytes(currentSystem.network?.bytes_recv || 0) }}</el-tag>
              </div>
            </template>
            <div ref="networkChart" class="chart-container"></div>
          </el-card>
        </el-col>
      </el-row>

      <!-- 详细数据表格 -->
      <el-row style="margin-top: 20px;">
        <el-col :span="24">
          <el-card class="monitor-card">
            <template #header>
              <div class="card-header">
                <span>实时数据</span>
                <el-button size="small" @click="clearData">清空数据</el-button>
              </div>
            </template>
            <el-table :data="recentData.slice(-10)" size="small" stripe>
              <el-table-column prop="timestamp" label="时间" width="200">
                <template #default="{ row }">
                  {{ new Date(row.timestamp).toLocaleTimeString() }}
                </template>
              </el-table-column>
              <el-table-column prop="avgTps" label="TPS" width="100" />
              <el-table-column prop="avgResponseTime" label="响应时间(ms)" width="120" />
              <el-table-column prop="totalRequests" label="总请求数" width="120" />
              <el-table-column prop="errorRate" label="错误率(%)" width="100" />
              <el-table-column prop="cpuPercent" label="CPU(%)" width="100" />
              <el-table-column prop="memoryPercent" label="内存(%)" width="100" />
            </el-table>
          </el-card>
        </el-col>
      </el-row>
    </div>
  </div>
</template>

<script>
import { ElMessage } from "element-plus";
import { mapState } from "vuex";
import {
  Connection, VideoPlay, VideoPause, Refresh
} from '@element-plus/icons-vue';
import * as echarts from 'echarts';

export default {
  name: 'PerformanceMonitor',
  components: {
    Connection, VideoPlay, VideoPause, Refresh
  },
  data() {
    return {
      websocket: null,
      connectionStatus: 'disconnected',
      isMonitoring: false,
      loading: false,
      currentData: {},
      currentSystem: {},
      recentData: [],
      charts: {},
      maxDataPoints: 50,
      // WebSocket连接管理
      reconnectAttempts: 0,
      maxReconnectAttempts: 5,
      reconnectInterval: 5000,
      reconnectTimer: null,
      heartbeatTimer: null,
      heartbeatInterval: 30000,
      isComponentDestroyed: false,
      connectionRetryBackoff: [1000, 2000, 5000, 10000, 30000] // 重连退避策略
    }
  },
  computed: {
    ...mapState({
      currentTaskId: state => state.currentTaskId || this.$route.params.taskId
    })
  },
  mounted() {
    this.initCharts();
    this.connectWebSocket();
    
    // 添加页面可见性监听，优化性能
    document.addEventListener('visibilitychange', this.handleVisibilityChange);
    
    // 添加窗口焦点监听
    window.addEventListener('focus', this.handleWindowFocus);
    window.addEventListener('blur', this.handleWindowBlur);
  },
  
  beforeUnmount() {
    // 标记组件已销毁
    this.isComponentDestroyed = true;
    
    // 清理WebSocket连接
    this.cleanupWebSocket();
    
    // 清理定时器
    this.clearAllTimers();
    
    // 清理图表
    this.destroyCharts();
    
    // 移除事件监听器
    document.removeEventListener('visibilitychange', this.handleVisibilityChange);
    window.removeEventListener('focus', this.handleWindowFocus);
    window.removeEventListener('blur', this.handleWindowBlur);
  },
  
  // 添加组件激活/停用处理（用于keep-alive）
  activated() {
    if (this.connectionStatus === 'disconnected' && !this.isComponentDestroyed) {
      this.connectWebSocket();
    }
  },
  
  deactivated() {
    // 组件被缓存时暂停连接
    this.pauseConnection();
  },
  methods: {
    initCharts() {
      this.$nextTick(() => {
        this.initTpsChart();
        this.initResponseChart();
        this.initCpuChart();
        this.initMemoryChart();
        this.initNetworkChart();
      });
    },

    initTpsChart() {
      const chartDom = this.$refs.tpsChart;
      if (!chartDom) return;
      
      this.charts.tps = echarts.init(chartDom);
      const option = {
        title: { text: 'TPS 趋势', left: 'center' },
        tooltip: { trigger: 'axis' },
        xAxis: { type: 'category', data: [] },
        yAxis: { type: 'value', name: 'TPS' },
        series: [{
          name: 'TPS',
          type: 'line',
          smooth: true,
          data: [],
          lineStyle: { color: '#409EFF' },
          areaStyle: { color: 'rgba(64, 158, 255, 0.3)' }
        }]
      };
      this.charts.tps.setOption(option);
    },

    initResponseChart() {
      const chartDom = this.$refs.responseChart;
      if (!chartDom) return;
      
      this.charts.response = echarts.init(chartDom);
      const option = {
        title: { text: '响应时间', left: 'center' },
        tooltip: { trigger: 'axis' },
        xAxis: { type: 'category', data: [] },
        yAxis: { type: 'value', name: '毫秒' },
        series: [{
          name: '平均响应时间',
          type: 'line',
          smooth: true,
          data: [],
          lineStyle: { color: '#67C23A' }
        }]
      };
      this.charts.response.setOption(option);
    },

    initCpuChart() {
      const chartDom = this.$refs.cpuChart;
      if (!chartDom) return;
      
      this.charts.cpu = echarts.init(chartDom);
      const option = {
        tooltip: { trigger: 'axis' },
        xAxis: { type: 'category', data: [] },
        yAxis: { type: 'value', name: '%', max: 100 },
        series: [{
          name: 'CPU',
          type: 'line',
          smooth: true,
          data: [],
          lineStyle: { color: '#E6A23C' },
          areaStyle: { color: 'rgba(230, 162, 60, 0.3)' }
        }]
      };
      this.charts.cpu.setOption(option);
    },

    initMemoryChart() {
      const chartDom = this.$refs.memoryChart;
      if (!chartDom) return;
      
      this.charts.memory = echarts.init(chartDom);
      const option = {
        tooltip: { trigger: 'axis' },
        xAxis: { type: 'category', data: [] },
        yAxis: { type: 'value', name: '%', max: 100 },
        series: [{
          name: '内存',
          type: 'line',
          smooth: true,
          data: [],
          lineStyle: { color: '#F56C6C' },
          areaStyle: { color: 'rgba(245, 108, 108, 0.3)' }
        }]
      };
      this.charts.memory.setOption(option);
    },

    initNetworkChart() {
      const chartDom = this.$refs.networkChart;
      if (!chartDom) return;
      
      this.charts.network = echarts.init(chartDom);
      const option = {
        tooltip: { trigger: 'axis' },
        xAxis: { type: 'category', data: [] },
        yAxis: { type: 'value', name: 'MB' },
        series: [
          {
            name: '接收',
            type: 'line',
            smooth: true,
            data: [],
            lineStyle: { color: '#909399' }
          },
          {
            name: '发送',
            type: 'line',
            smooth: true,
            data: [],
            lineStyle: { color: '#909399', type: 'dashed' }
          }
        ]
      };
      this.charts.network.setOption(option);
    },

    connectWebSocket() {
      // 如果组件已销毁，不进行连接
      if (this.isComponentDestroyed) return;
      
      if (!this.currentTaskId) {
        ElMessage.error('未找到任务ID');
        return;
      }

      // 清理现有连接
      this.cleanupWebSocket();

      const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
      const wsUrl = `${wsProtocol}//${window.location.host}/ws/performance/monitor/${this.currentTaskId}/`;
      
      try {
        this.websocket = new WebSocket(wsUrl);
        
        this.websocket.onopen = this.handleWebSocketOpen;
        this.websocket.onmessage = this.handleWebSocketMessage;
        this.websocket.onclose = this.handleWebSocketClose;
        this.websocket.onerror = this.handleWebSocketError;
        
        // 设置连接超时
        this.connectionTimeout = setTimeout(() => {
          if (this.websocket && this.websocket.readyState === WebSocket.CONNECTING) {
            this.websocket.close();
            this.handleConnectionTimeout();
          }
        }, 10000);
        
      } catch (error) {
        console.error('WebSocket连接创建失败:', error);
        this.handleConnectionError(error);
      }
    },

    handleWebSocketOpen() {
      if (this.isComponentDestroyed) return;
      
      this.connectionStatus = 'connected';
      this.reconnectAttempts = 0;
      this.clearReconnectTimer();
      
      ElMessage.success('WebSocket连接成功');
      
      // 清理连接超时
      if (this.connectionTimeout) {
        clearTimeout(this.connectionTimeout);
        this.connectionTimeout = null;
      }
      
      // 启动心跳检测
      this.startHeartbeat();
      
      // 获取当前状态
      this.getCurrentStatus();
    },

    handleWebSocketMessage(event) {
      if (this.isComponentDestroyed) return;
      
      try {
        const data = JSON.parse(event.data);
        this.processWebSocketMessage(data);
      } catch (error) {
        console.error('WebSocket消息解析失败:', error);
      }
    },

    handleWebSocketClose(event) {
      if (this.isComponentDestroyed) return;
      
      this.connectionStatus = 'disconnected';
      this.isMonitoring = false;
      this.stopHeartbeat();
      
      // 清理连接超时
      if (this.connectionTimeout) {
        clearTimeout(this.connectionTimeout);
        this.connectionTimeout = null;
      }
      
      console.log('WebSocket连接关闭:', event.code, event.reason);
      
      // 只有在非正常关闭时才尝试重连
      if (event.code !== 1000 && event.code !== 1001) {
        ElMessage.warning('WebSocket连接断开');
        this.attemptReconnect();
      }
    },

    handleWebSocketError(error) {
      if (this.isComponentDestroyed) return;
      
      console.error('WebSocket错误:', error);
      this.connectionStatus = 'disconnected';
      
      // 清理连接超时
      if (this.connectionTimeout) {
        clearTimeout(this.connectionTimeout);
        this.connectionTimeout = null;
      }
    },

    handleConnectionTimeout() {
      console.warn('WebSocket连接超时');
      ElMessage.error('WebSocket连接超时');
      this.connectionStatus = 'disconnected';
      this.attemptReconnect();
    },

    handleConnectionError(error) {
      console.error('WebSocket连接错误:', error);
      ElMessage.error('WebSocket连接错误');
      this.connectionStatus = 'disconnected';
      this.attemptReconnect();
    },

    processWebSocketMessage(data) {
      // 心跳响应
      if (data.type === 'pong') {
        this.lastPongTime = Date.now();
        return;
      }
      
      switch (data.type) {
        case 'connection_established':
          console.log('连接建立:', data.message);
          break;
        case 'current_status':
          this.updateCurrentData(data.data);
          break;
        case 'performance_update':
          this.updatePerformanceData(data.data);
          break;
        case 'test_started':
          ElMessage.success('性能测试已开始');
          break;
        case 'test_completed':
          ElMessage.success('性能测试已完成');
          this.isMonitoring = false;
          break;
        case 'test_failed':
          ElMessage.error('性能测试失败: ' + data.error);
          this.isMonitoring = false;
          break;
        case 'error':
          ElMessage.error(data.message);
          break;
        default:
          console.warn('未知的WebSocket消息类型:', data.type);
      }
    },

    attemptReconnect() {
      if (this.isComponentDestroyed || this.reconnectAttempts >= this.maxReconnectAttempts) {
        if (this.reconnectAttempts >= this.maxReconnectAttempts) {
          ElMessage.error('WebSocket重连失败，已达到最大重试次数');
        }
        return;
      }

      this.clearReconnectTimer();
      
      // 使用退避策略计算重连延迟
      const backoffIndex = Math.min(this.reconnectAttempts, this.connectionRetryBackoff.length - 1);
      const delay = this.connectionRetryBackoff[backoffIndex];
      
      console.log(`准备第 ${this.reconnectAttempts + 1} 次重连，延迟 ${delay}ms`);
      
      this.reconnectTimer = setTimeout(() => {
        if (!this.isComponentDestroyed) {
          this.reconnectAttempts++;
          this.connectWebSocket();
        }
      }, delay);
    },

    startHeartbeat() {
      this.stopHeartbeat();
      
      this.heartbeatTimer = setInterval(() => {
        if (this.websocket && this.websocket.readyState === WebSocket.OPEN) {
          this.websocket.send(JSON.stringify({ type: 'ping' }));
        }
      }, this.heartbeatInterval);
    },

    stopHeartbeat() {
      if (this.heartbeatTimer) {
        clearInterval(this.heartbeatTimer);
        this.heartbeatTimer = null;
      }
    },

    clearReconnectTimer() {
      if (this.reconnectTimer) {
        clearTimeout(this.reconnectTimer);
        this.reconnectTimer = null;
      }
    },

    clearAllTimers() {
      this.clearReconnectTimer();
      this.stopHeartbeat();
      
      if (this.connectionTimeout) {
        clearTimeout(this.connectionTimeout);
        this.connectionTimeout = null;
      }
    },

    cleanupWebSocket() {
      if (this.websocket) {
        // 移除事件监听器防止内存泄漏
        this.websocket.onopen = null;
        this.websocket.onmessage = null;
        this.websocket.onclose = null;
        this.websocket.onerror = null;
        
        // 关闭连接
        if (this.websocket.readyState === WebSocket.OPEN || 
            this.websocket.readyState === WebSocket.CONNECTING) {
          this.websocket.close(1000, 'Component cleanup');
        }
        
        this.websocket = null;
      }
      
      this.stopHeartbeat();
      this.clearReconnectTimer();
    },

    pauseConnection() {
      // 暂停连接但不清理资源（用于keep-alive）
      if (this.websocket) {
        this.websocket.close(1000, 'Component deactivated');
      }
      this.stopHeartbeat();
      this.clearReconnectTimer();
    },

    // 页面可见性变化处理
    handleVisibilityChange() {
      if (this.isComponentDestroyed) return;
      
      if (document.hidden) {
        // 页面隐藏时暂停连接
        this.pauseConnection();
      } else {
        // 页面显示时恢复连接
        if (this.connectionStatus === 'disconnected') {
          this.reconnectAttempts = 0;
          this.connectWebSocket();
        }
      }
    },

    // 窗口焦点处理
    handleWindowFocus() {
      if (this.isComponentDestroyed) return;
      
      if (this.connectionStatus === 'disconnected') {
        this.reconnectAttempts = 0;
        this.connectWebSocket();
      }
    },

    handleWindowBlur() {
      // 窗口失焦时可以选择性地暂停某些操作
      // 这里保持连接，只是记录日志
      console.log('窗口失去焦点');
    },

    disconnectWebSocket() {
      // 向后兼容的方法
      this.cleanupWebSocket();
    },

    updateCurrentData(data) {
      if (!data || this.isComponentDestroyed) return;
      
      // 深拷贝数据以防止引用导致的内存泄漏
      this.currentData = { ...data };
      
      // 添加到历史数据，使用优化的内存管理
      const timestamp = new Date().toISOString();
      const newDataPoint = {
        timestamp,
        avgTps: data.avg_tps || 0,
        avgResponseTime: data.avgResponseTime || 0,
        totalRequests: data.total_requests || 0,
        errorRate: data.error_rate || 0,
        cpuPercent: this.currentSystem.cpu?.percent || 0,
        memoryPercent: this.currentSystem.memory?.percent || 0,
        networkRecv: this.currentSystem.network?.bytes_recv || 0,
        networkSent: this.currentSystem.network?.bytes_sent || 0
      };
      
      // 使用更高效的数组管理
      this.addDataPoint(newDataPoint);
      
      // 批量更新图表，减少重绘频率
      this.scheduleChartUpdate();
    },

    updatePerformanceData(data) {
      if (!data || this.isComponentDestroyed) return;
      
      if (data.type === 'system_resources') {
        // 深拷贝系统数据
        this.currentSystem = { ...data.data };
      } else {
        // 合并性能数据
        this.currentData = { ...this.currentData, ...data };
      }
      
      this.scheduleChartUpdate();
    },

    addDataPoint(dataPoint) {
      this.recentData.push(dataPoint);
      
      // 当数据点超过最大限制时，批量删除旧数据而不是逐个删除
      if (this.recentData.length > this.maxDataPoints) {
        const excessData = this.recentData.length - this.maxDataPoints;
        this.recentData.splice(0, excessData);
      }
    },

    scheduleChartUpdate() {
      // 使用防抖来减少图表更新频率
      if (this.chartUpdateTimer) {
        clearTimeout(this.chartUpdateTimer);
      }
      
      this.chartUpdateTimer = setTimeout(() => {
        if (!this.isComponentDestroyed) {
          this.updateCharts();
        }
      }, 100); // 100ms防抖
    },

    updateCharts() {
      if (this.isComponentDestroyed || !this.recentData.length) return;
      
      // 批量处理数据，减少DOM操作
      const times = this.recentData.map(d => new Date(d.timestamp).toLocaleTimeString());
      
      // 使用批处理更新所有图表
      this.updateChartsInBatch(times);
    },

    updateChartsInBatch(times) {
      const chartUpdates = [
        {
          chart: this.charts.tps,
          data: this.recentData.map(d => d.avgTps)
        },
        {
          chart: this.charts.response,
          data: this.recentData.map(d => d.avgResponseTime)
        },
        {
          chart: this.charts.cpu,
          data: this.recentData.map(d => d.cpuPercent)
        },
        {
          chart: this.charts.memory,
          data: this.recentData.map(d => d.memoryPercent)
        }
      ];

      // 批量更新图表以提高性能
      chartUpdates.forEach(({ chart, data }) => {
        if (chart && chart.setOption) {
          try {
            chart.setOption({
              xAxis: { data: times },
              series: [{ data: data }]
            }, false, true); // 使用notMerge=false, lazyUpdate=true优化性能
          } catch (error) {
            console.warn('图表更新失败:', error);
          }
        }
      });
      
      // 单独更新网络图表（因为有两个数据系列）
      this.updateNetworkChart();
    },

    // 更新网络图表
    updateNetworkChart() {
      if (!this.charts.network) return;
      
      const times = this.recentData.map(d => new Date(d.timestamp).toLocaleTimeString());
      const networkRecvData = this.recentData.map(d => {
        const bytes = d.networkRecv || this.currentSystem.network?.bytes_recv || 0;
        return (bytes / 1024 / 1024).toFixed(2); // 转换为MB
      });
      const networkSentData = this.recentData.map(d => {
        const bytes = d.networkSent || this.currentSystem.network?.bytes_sent || 0;
        return (bytes / 1024 / 1024).toFixed(2); // 转换为MB
      });
      
      this.charts.network.setOption({
        xAxis: { data: times },
        series: [
          { data: networkRecvData },
          { data: networkSentData }
        ]
      });
    },

    toggleMonitoring() {
      if (this.connectionStatus !== 'connected') {
        ElMessage.error('WebSocket未连接');
        return;
      }
      
      this.loading = true;
      const action = this.isMonitoring ? 'stop_monitoring' : 'start_monitoring';
      
      this.websocket.send(JSON.stringify({ type: action }));
      
      setTimeout(() => {
        this.isMonitoring = !this.isMonitoring;
        this.loading = false;
      }, 1000);
    },

    getCurrentStatus() {
      if (this.connectionStatus === 'connected') {
        this.websocket.send(JSON.stringify({ type: 'get_current_status' }));
      }
    },

    refreshData() {
      this.getCurrentStatus();
      ElMessage.success('数据已刷新');
    },

    clearData() {
      // 清空数据数组，释放内存
      this.recentData.length = 0;
      this.currentData = {};
      this.currentSystem = {};
      
      // 立即更新图表
      this.updateCharts();
      ElMessage.success('数据已清空');
    },

    formatBytes(bytes) {
      if (bytes === 0) return '0 B';
      const k = 1024;
      const sizes = ['B', 'KB', 'MB', 'GB'];
      const i = Math.floor(Math.log(bytes) / Math.log(k));
      return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
    },

    destroyCharts() {
      // 清理图表更新定时器
      if (this.chartUpdateTimer) {
        clearTimeout(this.chartUpdateTimer);
        this.chartUpdateTimer = null;
      }
      
      // 销毁所有图表实例并清理引用
      Object.keys(this.charts).forEach(key => {
        const chart = this.charts[key];
        if (chart && typeof chart.dispose === 'function') {
          try {
            chart.dispose();
          } catch (error) {
            console.warn(`销毁图表 ${key} 时出错:`, error);
          }
        }
      });
      
      // 清空图表对象
      this.charts = {};
    }
  }
}
</script>

<style scoped>
.performance-monitor {
  padding: 20px;
  background-color: #f5f7fa;
  min-height: calc(100vh - 100px);
}

.monitor-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  background: white;
  padding: 16px 24px;
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
  margin-bottom: 20px;
}

.header-info {
  display: flex;
  align-items: center;
  gap: 20px;
}

.header-info h2 {
  margin: 0;
  font-size: 20px;
  font-weight: 600;
  color: #303133;
}

.monitor-controls {
  display: flex;
  gap: 10px;
}

.monitor-panels {
  flex: 1;
}

.monitor-card {
  margin-bottom: 20px;
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-weight: 600;
}

.chart-container {
  height: 300px;
  width: 100%;
}

:deep(.el-card__header) {
  padding: 15px 20px;
  border-bottom: 1px solid #ebeef5;
}

:deep(.el-card__body) {
  padding: 20px;
}

.connection-status {
  display: flex;
  align-items: center;
  gap: 8px;
}
</style>